package com.example.other.chat;

import com.example.authority.common.utils.SecurityUtils;
import com.example.authority.common.utils.SpringUtils;
import com.example.other.chat.config.Config;
import com.example.other.domain.Chat;
import com.example.other.service.ChatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * websocket服务端，接收websocket客户端长连接
 */
@ServerEndpoint("/websocket/api1/{id}/{doctorId}")
@Component
@Slf4j
public class WebSocketServer implements InitializingBean {
    public AmqpTemplate amqpTemplate= SpringUtils.getBean(AmqpTemplate.class);
    private RabbitTemplate rabbitTemplate=SpringUtils.getBean(RabbitTemplate.class);
    // 与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    public static ConcurrentHashMap<Session, List<Integer>> sessionToUser = new ConcurrentHashMap<>();
    // session集合,存放对应的session
    public static ConcurrentHashMap<Integer, Session> sessionPool = new ConcurrentHashMap<>();

    // concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。
    public static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();

    private static ChatService chatService=SpringUtils.getBean(ChatService.class);
    /**
     * 建立WebSocket连接
     *
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("id") Integer id,@PathParam("doctorId") Integer doctorId) {
        log.info("WebSocket建立连接中,连接用户ID：{}", id);
        try {
            Session historySession = sessionPool.get(doctorId);
            // historySession不为空,说明已经有人登陆账号,应该删除登陆的WebSocket对象
            if (historySession != null) {
                webSocketSet.remove(historySession);
                historySession.close();
            }
        } catch (IOException e) {
            log.error("重复登录异常,错误信息：" + e.getMessage(), e);
        }
        // 建立连接
        this.session = session;
        webSocketSet.add(this);
        sessionToUser.put(session, List.of(id,doctorId));
        sessionPool.put(doctorId, session);
        log.info("建立连接完成,当前在线人数为：{}", webSocketSet.size());
    }

    /**
     * 发生错误
     *
     * @param throwable e
     */
    @OnError
    public void onError(Throwable throwable) {
        throwable.printStackTrace();
    }

    /**
     * 连接关闭
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        sessionToUser.remove(session);
        log.info("连接断开,当前在线人数为：{}", webSocketSet.size());
    }

    /**
     * 接收客户端消息
     *
     * @param message 接收的消息
     */
    @OnMessage
    public void onMessage(String message) {
        Integer userId = sessionToUser.get(session).get(0);
        Integer doctorId = sessionToUser.get(session).get(1);
        log.info("收到客户端发来的消息：{}", message);
        Chat chat=new Chat();
        chat.setCosId(userId);
        chat.setContent(message);
        chat.setType(2);
        chat.setCreatedTime(new Date());
        chat.setDoctorId(doctorId);
        chatService.save(chat);
        amqpTemplate.convertAndSend("","chat_queue", chat);
    }

    /**
     * 推送消息到指定用户
     *
     * @param userId  用户ID
     * @param message 发送的消息
     */
    public static void sendMessageByUser(Integer userId, String message) {
        log.info("用户ID：" + userId + ",推送内容：" + message);
        Session session = sessionPool.get(userId);
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            log.error("推送消息到指定用户发生错误：" + e.getMessage(), e);
        }
    }

    /**
     * 群发消息
     *
     * @param message 发送的消息
     */
    public static void sendAllMessage(String message) {
        log.info("发送消息：{}", message);
        for (WebSocketServer webSocket : webSocketSet) {
            try {
                webSocket.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                log.error("群发消息发生错误：" + e.getMessage(), e);
            }
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
    }
}
